/**
 * Copyright 2013 wasu.com
 *
 *
 * Create on 2014-7-31 下午9:28:30
 */
package xiaojian.toolkit.netty.handler.codec.http.transformer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xiaojian.toolkit.bean.util.meta.Int2TypeMetainfo;
import xiaojian.toolkit.netty.handler.codec.http.transformer.HttpRequestTransformer;
import xiaojian.toolkit.netty.util.NettyConstants;

import com.alibaba.fastjson.JSON;

import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;

/**
 * 根据msgCode得到class，使用fastjson将request转换为requestbean。
 * 
 * @author <a href="mailto:caoxiaojian@wasu.com>xiaojian.cao</a>
 * 
 */
public class HttpJsonTransformer implements HttpRequestTransformer {

	private static final Logger logger = LoggerFactory
			.getLogger(HttpJsonTransformer.class);

	private Int2TypeMetainfo int2TypeMetainfo = null;
	private int dumpBytes = 1024;

	/**
	 * @see stc.skymobi.util.Transformer#transform(java.lang.Object)
	 */
	@Override
	public Object transform(FullHttpRequest request) {
		int contentLength = 0;

		try {
			String value = request.headers().get(
					HttpHeaders.Names.CONTENT_LENGTH);
			contentLength = Integer.parseInt(value);
		} catch (Exception e) {
			logger.error("transform", e);
		}

		String strMsgCode = request.headers().get(
				NettyConstants.HEADER_MESSAGE_CODE);
		if (strMsgCode == null || strMsgCode.trim().length() == 0) {
			logger.error("Cannot get MsgCode from request[{}].", request);
			return null;
		}

		String contentType = request.headers().get(
				HttpHeaders.Names.CONTENT_TYPE);
		if (contentType == null) {
			throw new RuntimeException(
					"Cannot found content_type from request[" + request + "].");
		}

//		if (!contentType.equals(NettyConstants.JSON_TYPE)) {
//			throw new RuntimeException("Invalid content type[" + contentType
//					+ "] , must be[" + NettyConstants.JSON_TYPE + "], request["
//					+ request + "].");
//		}

		int msgCode = Integer.parseInt(strMsgCode);
		Class<?> targetType = int2TypeMetainfo.find(msgCode);
		if (targetType == null) {
			throw new RuntimeException("Cannot found clazz with msgCode["
					+ msgCode + "].");
		}

		if (contentLength > 0) {
			byte[] bytes = new byte[contentLength];
			request.content().readBytes(bytes);

			if (logger.isTraceEnabled()) {
				logger.trace("decodes raw bytes -->");
				logger.trace(new String(bytes));
			}

			Object bean = null;
			try {
				bean = JSON.parseObject(bytes, targetType);
			} catch (Exception exception) {
				logger.error("[Json]parse[" + new String(bytes) + "] fail.",
						exception);
				throw new RuntimeException("Parse string[" + new String(bytes)
						+ "] fail.");
			}

			return bean;
		}

		return null;
	}

	/**
	 * @return the int2TypeMetainfo
	 */
	public Int2TypeMetainfo getInt2TypeMetainfo() {
		return int2TypeMetainfo;
	}

	/**
	 * @param int2TypeMetainfo
	 *            the int2TypeMetainfo to set
	 */
	public void setInt2TypeMetainfo(Int2TypeMetainfo int2TypeMetainfo) {
		this.int2TypeMetainfo = int2TypeMetainfo;
	}

	/**
	 * @return the dumpBytes
	 */
	public int getDumpBytes() {
		return dumpBytes;
	}

	/**
	 * @param dumpBytes
	 *            the dumpBytes to set
	 */
	public void setDumpBytes(int dumpBytes) {
		this.dumpBytes = dumpBytes;
	}

}
